package com.codingclub.domain.service.impl;

import com.codingclub.common.entity.PageResult;
import com.codingclub.common.enums.ErrCode;
import com.codingclub.common.enums.SubjectInfoTypeEnum;
import com.codingclub.common.exception.BusinessException;
import com.codingclub.domain.bo.SubjectInfoBO;
import com.codingclub.domain.convert.SubjectInfoConverter;
import com.codingclub.domain.handle.subject.SubjectTypeHandler;
import com.codingclub.domain.handle.subject.SubjectTypeHandlerFactory;
import com.codingclub.domain.service.SubjectInfoDomainService;
import com.codingclub.infra.basic.entity.SubjectInfo;
import com.codingclub.infra.basic.entity.SubjectLabel;
import com.codingclub.infra.basic.entity.SubjectMapping;
import com.codingclub.infra.basic.service.SubjectInfoService;
import com.codingclub.infra.basic.service.SubjectLabelService;
import com.codingclub.infra.basic.service.SubjectMappingService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SubjectInfoDomainServiceImpl implements SubjectInfoDomainService {
    private final SubjectInfoService subjectInfoService;
    private final SubjectMappingService subjectMappingService;
    private final SubjectLabelService subjectLabelService;
    //构造函数注入对象
    public SubjectInfoDomainServiceImpl(SubjectInfoService subjectInfoService, SubjectMappingService subjectMappingService, SubjectLabelService subjectLabelService) {
        this.subjectInfoService = subjectInfoService;
        this.subjectMappingService = subjectMappingService;
        this.subjectLabelService = subjectLabelService;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public boolean add(SubjectInfoBO subjectInfoBO) {
        SubjectInfo subjectInfo = SubjectInfoConverter.INSTANCE.covertBoToEntity(subjectInfoBO);
        boolean b = subjectInfoService.insert(subjectInfo);
        if(!b)throw new BusinessException(ErrCode.OPERATION_ERROR);
        //赋值自增id
        subjectInfoBO.setId(subjectInfo.getId());
        //插入题目的选项和答案
        SubjectTypeHandler handle = SubjectTypeHandlerFactory.getHandle(SubjectInfoTypeEnum.getByCode(subjectInfoBO.getSubjectType()));
        boolean add = handle.add(subjectInfoBO);
        if(!add)throw new BusinessException(ErrCode.OPERATION_ERROR);
        //插入题目标签及分类
        List<Long> categoryIds = subjectInfoBO.getCategoryIds();
        List<Long> labelIds = subjectInfoBO.getLabelIds();
        if(categoryIds==null||labelIds==null||categoryIds.isEmpty()||labelIds.isEmpty()){
            throw new BusinessException(ErrCode.PARAMS_ERROR);
        }
        List<SubjectMapping>subjectMappingList=new ArrayList<>();
        Long subjectId = subjectInfo.getId();
        //这里采用多对多 比如管理员选了3个分类一个标签 将会插入三条数据（暂时不知道为什么）
        for (Long categoryId : categoryIds) {
            for (Long labelId : labelIds) {
                SubjectMapping subjectMapping = new SubjectMapping();
                subjectMapping.setCategoryId(categoryId);
                subjectMapping.setLabelId(labelId);
                subjectMapping.setSubjectId(subjectId);
                subjectMappingList.add(subjectMapping);
            }
        }
        add=subjectMappingService.batchInsert(subjectMappingList);
        if(!add)throw new BusinessException(ErrCode.OPERATION_ERROR);
        return true;
    }

    @Override
    public PageResult<SubjectInfoBO> getSubjectPage(SubjectInfoBO subjectInfoBO) {
        PageResult<SubjectInfoBO> pageResult = new PageResult<>();
        pageResult.setPageNo(subjectInfoBO.getPageNo());
        pageResult.setPageSize(subjectInfoBO.getPageSize());
        SubjectInfo subjectInfo = SubjectInfoConverter.INSTANCE.covertBoToEntity(subjectInfoBO);
        int count = subjectInfoService.countByCondition(subjectInfo,subjectInfoBO.getCategoryId(),subjectInfoBO.getLabelId());
        //0条记录就直接返回
        if(count==0){
            return pageResult;
        }
        int start = (subjectInfoBO.getPageNo() - 1) * subjectInfoBO.getPageSize();
        List<SubjectInfo> subjectInfoList = subjectInfoService.queryPage(subjectInfo, subjectInfoBO.getCategoryId()
                , subjectInfoBO.getLabelId(), start, subjectInfoBO.getPageSize());
        List<SubjectInfoBO> subjectInfoBOS = SubjectInfoConverter.INSTANCE.convertListInfoToBO(subjectInfoList);
        subjectInfoBOS.forEach(info -> {
            SubjectMapping subjectMapping = new SubjectMapping();
            subjectMapping.setSubjectId(info.getId());
            List<SubjectMapping> mappingList = subjectMappingService.query(subjectMapping);
            List<Long> labelIds = mappingList.stream().map(SubjectMapping::getLabelId).collect(Collectors.toList());
            List<SubjectLabel> labelList = subjectLabelService.batchQueryById(labelIds);
            List<String> labelNames = labelList.stream().map(SubjectLabel::getLabelName).collect(Collectors.toList());
            info.setLabelNames(labelNames);
        });
        pageResult.setRecords(subjectInfoBOS);
        pageResult.setTotal(count);
        return pageResult;
    }
}
